package com.jrmf.redenvelopes.order.controller;

import com.jrmf.redenvelopes.order.job.*;
import com.jrmf.redenvelopes.order.model.DepositdataMfkjImportlog;
import com.jrmf.redenvelopes.order.service.AsyncService;
import com.jrmf.redenvelopes.order.util.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Result;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.*;


@RestController
@RequestMapping("jobManagementController")
@Api(value = "jobManagementController", description = "任务管理器")
public class JobManagementController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private Scheduler scheduler;
    @Autowired
    private AsyncService asyncService;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @ApiOperation(value = "异步执行数据汇总任务样例", notes = "入金数据ETL")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/asyncBatchJobsDemo")
    public void asyncBatchJobs(@RequestParam(value="startTime")String startTime,@RequestParam(value="endTime")String endTime)
    {
        logger.info("开始。。。");
        asyncService.executeAsync();
        logger.info("结束。。。");
    }


    @ApiOperation(value = "添加一个入金数据ETL任务", notes = "添加任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cronExpression", value = "任务触发时间表达式", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/addDepositDataETLJob")
    public void addDepositDataETLJob(@RequestParam(value="cronExpression")String cronExpression)
    {
        startDepositDataETLJob(cronExpression);
    }

    /**
     * 暂停某个任务
     *
     * @param name
     * @param group
     * @throws SchedulerException
     */
    @ApiOperation(value = "暂停某个任务", notes = "暂停某个任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "任务名称", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "group", value = "任务组", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/pauseJob")
    public void pauseJob(@RequestParam(value="name")String name,@RequestParam(value="group") String group) throws SchedulerException {
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null)
            return;
        scheduler.pauseJob(jobKey);
    }
    /**
     * 暂停所有任务
     *
     * @throws SchedulerException
     */
    public void pauseAllJob() throws SchedulerException {
        scheduler.pauseAll();
    }

    /**
     * 恢复所有任务
     *
     * @throws SchedulerException
     */
    public void resumeAllJob() throws SchedulerException {
        scheduler.resumeAll();
    }

    /**
     * 恢复某个任务
     *
     * @param name
     * @param group
     * @throws SchedulerException
     */
    @ApiOperation(value = "恢复某个任务", notes = "恢复某个任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "任务名称", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "group", value = "任务组", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/resumeJob")
    public void resumeJob(@RequestParam(value="name")String name,@RequestParam(value="group") String group) throws SchedulerException {
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null)
            return;
        scheduler.resumeJob(jobKey);
    }

    /**
     * 删除某个任务
     *
     * @param name
     * @param group
     * @throws SchedulerException
     */
    @ApiOperation(value = "删除某个任务", notes = "删除某个任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "任务名称", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "group", value = "任务组", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/deleteJob")
    public void deleteJob(@RequestParam(value="name")String name,@RequestParam(value="group") String group) throws SchedulerException {
        JobKey jobKey = new JobKey(name, group);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null)
            return;
        scheduler.deleteJob(jobKey);
    }

    /**
     * 修改某个任务的执行时间
     *
     * @param name
     * @param group
     * @param time
     * @return
     * @throws SchedulerException
     */
    @ApiOperation(value = "修改某个任务执行时间", notes = "修改某个任务执行时间")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "任务名称", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "group", value = "任务组", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "time", value = "修改后的任务执行时间", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/modifyJob")
    public boolean modifyJob(@RequestParam(value="name")String name, @RequestParam(value="group")String group, @RequestParam(value="time")String time) throws SchedulerException {
        Date date = null;
        TriggerKey triggerKey = new TriggerKey(name, group);
        CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        String oldTime = cronTrigger.getCronExpression();
        if (!oldTime.equalsIgnoreCase(time)) {
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group)
                    .withSchedule(cronScheduleBuilder).build();
            date = scheduler.rescheduleJob(triggerKey, trigger);
        }
        return date != null;
    }


    @ApiOperation(value = "添加一个对账任务", notes = "添加一个对账任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "contrastDate", value = "对帐数据日期", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "platformType", value = "平台来源", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "cronExpression", value = "任务触发时间表达式", required = true, dataType = "String", paramType = "query"),
})
    @PostMapping(value="/addAccountCheckJob")
    public void addAccountCheckJob(@RequestParam(value="contrastDate")String contrastDate,@RequestParam(value="platformType")String platformType,@RequestParam(value="cronExpression")String cronExpression)
    {
        //contrastDate  = DateUtil.dateToStr(DateUtil.getDaysBefore(2),"yyyyMMdd");//默认对前天的帐 todo
        startAccountCheckJob(contrastDate,platformType,cronExpression);
    }

    public void startDepositDataETLJob(String cronExpression){

        // 启动调度器
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        //构建job信息
        String jobName ="job"+UUID.randomUUID();
        String jobGroupName = "depositDataETLJobGroup";
        String triGroupName = "depositDataETLTriggerGroup";
        String triggerName ="tri"+UUID.randomUUID();
        JobDetail jobDetail = JobBuilder.newJob(DepositDataETLJob.class).withIdentity(jobName, jobGroupName).build();

        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triGroupName)
                .withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);

        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void startAccountCheckJob(String contrastDate,String platformType,String cronExpression){

        // 启动调度器
        try {
            scheduler.start();//todo
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        //构建job信息
        String jobName ="job"+UUID.randomUUID();
        String jobGroupName = "accountCheckJobGroup";
        String triGroupName = "accountCheckTriggerGroup";
        String triggerName ="tri"+UUID.randomUUID();
        JobDetail jobDetail = JobBuilder.newJob(AccountCheckJob.class).withIdentity(jobName, jobGroupName).
                usingJobData("contrastDate",contrastDate).usingJobData("platformType",platformType).build();

        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triGroupName)
                .withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);

        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "多线程执行任务异步返回结果样例", notes = "多线程执行任务异步返回结果样例")
    @PostMapping(value="/batchCallAble")
    public  List<String>  batchCallAble(@RequestParam(value="startTime")String startTime, @RequestParam(value="endTime")String endTime)
    {
        logger.info(startTime);
        logger.info(endTime);
        List<String> futureList = new ArrayList<>();
        logger.info("开始。。。");
        CompletionService cs =new ExecutorCompletionService(taskExecutor);
        for (int i=0;i<10;i++){//执行汇总数据，返回每天的执行结果list<DepositdataMfkjImportlog>
            DepositDataETLThreads threads =new DepositDataETLThreads(i);
            cs.submit(threads);


            //Future<String> f =taskExecutor.submit(threads);
           /* try {
                logger.info("获取线程执行结果:"+f.get());//future的get()方法会阻塞 变成同步的逻辑，这是future的缺陷
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }*/
        }
        try {
            for (int i=0;i<10;i++){
               // logger.info("等待打印的"+i+"个返回值");
                Future<String> f =cs.take();
                futureList.add(f.get());
                //logger.info(i+"后置"+cs.take().get().toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info("结束。。。");
        return  futureList;
    }

    @ApiOperation(value = "多线程批量执行入金ETL任务", notes = "多线程批量执行入金ETL任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/batchExeDepositDataETLThreads")
    public  String  batchExeDepositDataETLThreads (@RequestParam(value="startTime")String startTime, @RequestParam(value="endTime")String endTime)
    {
        List<String> days =DateUtil.getBetweenDate(startTime,endTime,"yyyyMMdd");

        //获取任务执行结果
        List<DepositdataMfkjImportlog> futureList = new ArrayList<>();
        logger.info("开始。。。");
        CompletionService cs =new ExecutorCompletionService(taskExecutor);
        for (int i=0;i<days.size();i++){//执行汇总数据，返回每天的执行结果list<DepositdataMfkjImportlog> todo
            DepositDataETLCallable ddc  =new DepositDataETLCallable(days.get(i));
            cs.submit(ddc);
        }

        /*try {
            for (int i=0;i<days.size();i++){
                Future<DepositdataMfkjImportlog> f =cs.take();
                futureList.add(f.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        logger.info("结束。。。");
        return  "1";
    }


    @PostMapping(value="/ceshi")
    public  String  test (@RequestParam(value="remark")String remark)
    {

    return  null;
    }

    @ApiOperation(value = "多线程批量执行入金ETL任务", notes = "多线程批量执行入金ETL任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "platformType", value = "支付平台", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/batchExeAccountCheckThreads")
    public  String  batchExeAccountCheckThreads (@RequestParam(value="startTime")String startTime, @RequestParam(value="endTime")String endTime,@RequestParam(value="platformType")String platformType)
    {
        List<String> days =DateUtil.getBetweenDate(startTime,endTime,"yyyyMMdd");

        //获取任务执行结果
        //List<DepositdataMfkjImportlog> futureList = new ArrayList<>();
        logger.info("开始。。。");
        CompletionService cs =new ExecutorCompletionService(taskExecutor);
        for (int i=0;i<days.size();i++){
            AccountCheckCallable ddc  =new AccountCheckCallable(days.get(i),platformType);
            cs.submit(ddc);
        }

        /*try {
            for (int i=0;i<days.size();i++){
                Future<DepositdataMfkjImportlog> f =cs.take();
                futureList.add(f.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        logger.info("结束。。。");
        return  "1";
    }


    @ApiOperation(value = "多线程批量执行差错计算", notes = "多线程批量执行差错计算")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "platformType", value = "支付平台", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/batchExeAccountCheck4Threads")
    public  String  batchExeAccountCheck4Threads (@RequestParam(value="startTime")String startTime, @RequestParam(value="endTime")String endTime,@RequestParam(value="platformType")String platformType)
    {
        List<String> days =DateUtil.getBetweenDate(startTime,endTime,"yyyyMMdd");

        //获取任务执行结果
        //List<DepositdataMfkjImportlog> futureList = new ArrayList<>();
        logger.info("开始。。。");
        CompletionService cs =new ExecutorCompletionService(taskExecutor);
        for (int i=0;i<days.size();i++){
            AccountCheck4Callable ddc  =new AccountCheck4Callable(days.get(i),platformType);
            cs.submit(ddc);
        }

        /*try {
            for (int i=0;i<days.size();i++){
                Future<DepositdataMfkjImportlog> f =cs.take();
                futureList.add(f.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        logger.info("结束。。。");
        return  "1";
    }

    @ApiOperation(value = "多线程批量执行差错计算补齐时间戳对不齐数据", notes = "多线程批量执行差错计算补齐时间戳对不齐数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "起始时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "platformType", value = "支付平台", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value="/batchExeAccountCheck5Threads")
    public  String  batchExeAccountCheck5Threads (@RequestParam(value="startTime")String startTime, @RequestParam(value="endTime")String endTime,@RequestParam(value="platformType")String platformType)
    {
        List<String> days =DateUtil.getBetweenDate(startTime,endTime,"yyyyMMdd");

        //获取任务执行结果
        //List<DepositdataMfkjImportlog> futureList = new ArrayList<>();
        logger.info("开始。。。");
        CompletionService cs =new ExecutorCompletionService(taskExecutor);
        for (int i=0;i<days.size();i++){
            AccountCheck3and4Callable ddc  =new AccountCheck3and4Callable(days.get(i),platformType);
            cs.submit(ddc);
        }

        /*try {
            for (int i=0;i<days.size();i++){
                Future<DepositdataMfkjImportlog> f =cs.take();
                futureList.add(f.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        logger.info("结束。。。");
        return  "1";
    }
}
